package com.xinqi.modules.databank.v2.service.analysis.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xinqi.common.base.dto.QuestionBaseDTO;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.core.enums.CourseContentTypeEnum;
import com.xinqi.common.core.enums.ResourcePartTypeEnum;
import com.xinqi.modules.databank.v1.domain.CourseInteractionSubmitEntity;
import com.xinqi.modules.databank.v1.domain.CourseQuestionLibraryEntity;
import com.xinqi.modules.databank.dto.req.InteractionSubmitQueryDTO;
import com.xinqi.modules.databank.dto.req.ResourceAnalysisQueryDTO;
import com.xinqi.modules.databank.dto.req.ResourceQuestionAnalysisQueryDTO;
import com.xinqi.modules.databank.dto.req.question.CommonDataFileDTO;
import com.xinqi.modules.databank.dto.req.question.QuestionRateDTO;
import com.xinqi.modules.databank.dto.req.question.ResourceAnswerDTO;
import com.xinqi.modules.databank.dto.rsp.*;
import com.xinqi.modules.databank.dto.rsp.question.QuestionAnalysisResultDTO;
import com.xinqi.modules.databank.v1.manager.CourseQuestionLibraryManager;
import com.xinqi.modules.databank.v2.convert.*;
import com.xinqi.modules.databank.v2.domain.*;
import com.xinqi.modules.databank.v2.manager.*;
import com.xinqi.modules.databank.v2.service.analysis.CourseResourceAnalysisService;
import com.xinqi.modules.databank.v1.manager.CourseInteractionSubmitManager;
import com.xinqi.modules.databank.v2.util.MathUtils;
import com.xinqi.modules.databank.v2.util.QuestionUtil;
import com.xinqi.modules.databank.v2.util.ResourceUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 资料库试题分析Manager层
 * @author dzy
 */
@Service
@RequiredArgsConstructor
public class CourseResourceAnalysisServiceImpl implements CourseResourceAnalysisService {

    private final CourseResourceBaseManager courseResourceBaseManager;

    private final CourseResourceStudentLogManager resourceStudentLogManager;

    private final CourseResourcePartManager courseResourcePartManager;

    private final ResourceInteractionLogManager resourceInteractionLogManage;

    private final CourseResourceQuestionConvert resourceQuestionConvert;
    private final CourseQuestionLibraryManager questionLibraryManager;

    private final CourseResourceAnalysisManager courseResourceAnalysisManager;

    private final CourseResourceInteractionLogConvert resourceInteractionLogConvert;

    private final CourseResourceAnswerConvert courseResourceAnswerConvert;
    private final CourseInteractionSubmitManager courseInteractionSubmitManager;

    private final CourseQuestionLibraryConvert courseQuestionLibraryConvert;
    private final CourseQuestionLibraryManager courseQuestionLibraryManager;

    /**
     * 更新试题分析
     * @author dzy
     */
    @Override
    public void refreshQuestionAnalysis(Long contentId) {

        // 判断是否数据存在
        CourseResourceEntity entity = Optional.ofNullable(courseResourceBaseManager.getById(contentId))
            .orElseThrow(() -> CommonErrors.NOT_DATA.asException("course.resource.data.id.not.exit"));

        // 获取学生日志列表
        List<CourseResourceStudentLogEntity> logList = resourceStudentLogManager.listByContentId(contentId);

        // 获取互动环节试题
        LambdaQueryWrapper<CourseResourcePartEntity> partWrapper= new LambdaQueryWrapper<>();
        partWrapper.eq(CourseResourcePartEntity::getContentId, contentId);
        partWrapper.eq(CourseResourcePartEntity::getInteractionType, ResourcePartTypeEnum.QUESTION.getCode());
        partWrapper.orderByAsc(CourseResourcePartEntity::getTimePause);
        List<CourseResourcePartEntity> partList = courseResourcePartManager.list(partWrapper);

        List<QuestionBaseDTO> questionList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(partList)) {
            for (CourseResourcePartEntity part : partList) {
                if (CollectionUtils.isNotEmpty(part.getQuestions())) {
                    questionList.addAll(part.getQuestions());
                }
            }
        }

        // 未获取到试题 查询旧题数据是否存在 (互动视频)
        if (Objects.equals(CourseContentTypeEnum.INTERACTIVE_VIDEO.getCode(), entity.getContentType())
            && CollectionUtils.isEmpty(questionList)) {
            LambdaQueryWrapper<CourseQuestionLibraryEntity> libraryWrapper = new LambdaQueryWrapper<>();
            libraryWrapper.eq(CourseQuestionLibraryEntity::getContentId, contentId);
            List<CourseQuestionLibraryEntity> libraryList = courseQuestionLibraryManager.list(libraryWrapper);
            questionList = courseQuestionLibraryConvert.convertBase(libraryList);
        }

        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(questionList), "未添加试题");

        BigDecimal score = questionList.stream().map(QuestionBaseDTO::getScore).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 获取学生答题信息
        List<ResourceInteractionLogResultDTO> interactionList = resourceInteractionLogManage.findList(contentId, null);
        List<ResourceAnswerDTO> answerList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(interactionList)) {
            interactionList.forEach(item -> {
                item.getAnswer().forEach(answer -> {
                    answer.setStudentId(item.getStudentId());
                    answerList.add(answer);
                });
            });
        }

        // 获取旧版本版本学生答题数据
        List<CourseInteractionSubmitEntity> answerOldList = courseInteractionSubmitManager.findStudentAnswer(contentId, null, null);
        if (CollectionUtils.isNotEmpty(answerOldList)) {
            answerList.addAll(courseResourceAnswerConvert.convertBaseAnswerList(answerOldList));
        }

        // 统计答题人数
        Integer answerCount = 0;
        if (CollectionUtils.isNotEmpty(answerList)) {
            answerCount = answerList.stream().collect(Collectors.groupingBy(ResourceAnswerDTO::getStudentId)).size();
        }

        // 校验是否试题分析是否已存在
        LambdaQueryWrapper<CourseResourceAnalysisEntity> analysisWrapper = new LambdaQueryWrapper<>();
        analysisWrapper.eq(CourseResourceAnalysisEntity::getContentId, contentId);
        CourseResourceAnalysisEntity analysis = courseResourceAnalysisManager.getOne(analysisWrapper);
        if (Objects.isNull(analysis)) {
            analysis = new CourseResourceAnalysisEntity();
            analysis.setClassId(entity.getClassId());
            analysis.setContentId(contentId);
            analysis.setContentType(entity.getContentType());
        }

        analysis.setScore(score);
        analysis.setQuestionNum(questionList.size());
        analysis.setStudentNum(logList.size());
        analysis.setAnswerNum(answerCount);

        // 计算平均分/答题得分率
        BigDecimal allScore = logList.stream().map(CourseResourceStudentLogEntity::getStudentScore).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (answerCount == 0) {
            analysis.setAvgScore(new BigDecimal(0));
            analysis.setScoreRate(new BigDecimal(0));
        } else {
            // 计算平均分
            BigDecimal avgScore = allScore.divide(new BigDecimal(answerCount), 2, BigDecimal.ROUND_HALF_UP);
            analysis.setAvgScore(MathUtils.stripTrailingZeros(avgScore, 1));
            // 计算答题得分率
            BigDecimal scoreRate = allScore.divide(score, 2, BigDecimal.ROUND_HALF_UP);
            analysis.setScoreRate(scoreRate);
        }

        // 计算答题正确率
        List<ResourceAnswerDTO> rightAnswers = answerList.stream().filter(v -> v.getIsRight()).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(answerList)) {
            BigDecimal avgRate = new BigDecimal(rightAnswers.size()).divide(new BigDecimal(answerList.size()), 2, BigDecimal.ROUND_DOWN);
            analysis.setAvgRate(MathUtils.stripTrailingZeros(avgRate, 1));
        } else {
            analysis.setAvgRate(new BigDecimal(0));
        }

        // 计算过每道题正确率
        List<QuestionRateDTO> questionRate = new ArrayList<>();
        Map<Long, List<ResourceAnswerDTO>> map = answerList.stream().collect(Collectors.groupingBy(ResourceAnswerDTO::getQuestionId));
        questionList.forEach(question -> {
            questionRate.add(calcQuestionRate(contentId, question, map.get(question.getId())));
        });
        analysis.setQuestionRate(questionRate);

        courseResourceAnalysisManager.saveOrUpdate(analysis);

    }

    /**
     * 计算试题得分率
     * @author dzy
     */
    private QuestionRateDTO calcQuestionRate(Long contentId, QuestionBaseDTO question, List<ResourceAnswerDTO> list) {
        QuestionRateDTO questionRate = new QuestionRateDTO();
        questionRate.setContentId(contentId);
        questionRate.setQuestionId(question.getId());
        questionRate.setContent(question.getContent());
        questionRate.setType(question.getType());

        // 计算得分率
        if (CollectionUtils.isNotEmpty(list)) {
            List<ResourceAnswerDTO> rightAnswers = list.stream().filter(v -> v.getIsRight()).collect(Collectors.toList());
            BigDecimal avgRate = new BigDecimal(rightAnswers.size()).divide(new BigDecimal(list.size()), 2, BigDecimal.ROUND_DOWN);
            questionRate.setScoreRate(MathUtils.stripTrailingZeros(avgRate, 1));
        } else {
            questionRate.setScoreRate(new BigDecimal(0));
        }
        return questionRate;
    }


    /**
     * 获取试题分析
     * @author dzy
     */
    @Override
    public ResourceAnalysisResultDTO findQuestionAnalysis(ResourceAnalysisQueryDTO query) {

        // 判断是否数据存在
        CourseResourceEntity entity = Optional.ofNullable(courseResourceBaseManager.getById(query.getContentId()))
            .orElseThrow(() -> CommonErrors.NOT_DATA.asException("course.resource.data.id.not.exit"));

        // 获取分析数据
        ResourceAnalysisResultDTO result = courseResourceAnalysisManager.findQuestionAnalysis(query);

        if (Objects.nonNull(result)) {

            // 获取互动环节信息
            List<InteractiveDTO> list = new ArrayList<>();
            LambdaQueryWrapper<CourseResourcePartEntity> partWrapper = new LambdaQueryWrapper<>();
            partWrapper.eq(CourseResourcePartEntity::getContentId, entity.getId());
            if (Objects.equals(CourseContentTypeEnum.DATA.getCode(), entity.getContentType())) {
                List<CommonDataFileDTO> fileDTOS = ResourceUtil.getDataFile(entity);
                List<Long> fileIds = fileDTOS.stream().map(v -> v.getId()).collect(Collectors.toList());
                partWrapper.in(CourseResourcePartEntity::getResourceId, fileIds);
                List<CourseResourcePartEntity> partList = courseResourcePartManager.list(partWrapper);
                list.addAll(ResourceUtil.tranInteractive(entity, partList, fileDTOS));
            } else {
                partWrapper.orderByAsc(CourseResourcePartEntity::getTimePause);
                List<CourseResourcePartEntity> partList = courseResourcePartManager.list(partWrapper);
                list.addAll(ResourceUtil.tranInteractive(entity, partList, null));
            }
            result.setInteractiveList(list);

            // 获取学生日志列表
            List<StudentScoreResultDTO> logList = resourceStudentLogManager.studentScoreList(query.getContentId());
            result.setLogList(logList);

            List<MarkRangeResultDTO> rangeList = QuestionUtil.generateMarkRange();
            rangeList.forEach(item -> {
                BigDecimal minScore = result.getScore().multiply(new BigDecimal(item.getMin())).divide(new BigDecimal(100));
                BigDecimal maxScore = result.getScore().multiply(new BigDecimal(item.getMax())).divide(new BigDecimal(100));
                if (Objects.equals(100, item.getMax())) {
                    Long count = logList.stream()
                        .filter(v -> v.getScore().compareTo(minScore) >= 0 && v.getScore().compareTo(maxScore) <= 0).count();
                    item.setCount(count);
                } else {
                    Long count = logList.stream()
                        .filter(v -> v.getScore().compareTo(minScore) >= 0 && v.getScore().compareTo(maxScore) < 0).count();
                    item.setCount(count);
                }

            });
            result.setMarkRange(rangeList);
        }

        return result;

    }

    /**
     * 获取 文件或互动环节 试题 解析
     * @author dzy
     */
    @Override
    public List<QuestionAnalysisResultDTO> questionAnalysisList(ResourceQuestionAnalysisQueryDTO query) {

        // 获取互动环节
        CourseResourcePartEntity part = getPartById(query.getPartId());
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(part), "未获取到互动环节");

        // 判断资料库数据据存在
        CourseResourceEntity entity = Optional.ofNullable(courseResourceBaseManager.getById(query.getContentId()))
            .orElseThrow(() -> CommonErrors.NOT_DATA.asException("course.resource.data.id.not.exit"));

        // 互动视频 旧数据试题获取
        if (CollectionUtils.isEmpty(part.getQuestions())) {
            if (Objects.equals(CourseContentTypeEnum.INTERACTIVE_VIDEO.getCode(), entity.getContentType())) {
                List<CourseQuestionLibraryEntity> oldQuestions = questionLibraryManager.findByPartId(query.getPartId());
                List<QuestionBaseDTO> questions = courseQuestionLibraryConvert.convertBase(oldQuestions);
                // 转换选项
                part.setQuestions(QuestionUtil.tranOptionList(questions));
            }
        }

        // 校验试题是否存在
        CommonErrors.BAD_REQUEST.check(CollectionUtils.isNotEmpty(part.getQuestions()), "未获取到试题");

        // 获取试题
        List<QuestionAnalysisResultDTO> result = resourceQuestionConvert.convertQuestionList(part.getQuestions());

        // 统计试题信息
        this.calLibraryTotal(part, result);

        return result;
    }

    /**
     * 获取互动环节
     */
    private CourseResourcePartEntity getPartById(Long partId) {
        // 获取试题
        LambdaQueryWrapper<CourseResourcePartEntity> partWrapper= new LambdaQueryWrapper<>();
        partWrapper.eq(CourseResourcePartEntity::getId, partId);
        partWrapper.eq(CourseResourcePartEntity::getInteractionType, ResourcePartTypeEnum.QUESTION.getCode());
        return courseResourcePartManager.getOne(partWrapper);
    }

    /**
     * 统计每道题的答题详情
     */
    private void calLibraryTotal(CourseResourcePartEntity part, List<QuestionAnalysisResultDTO> analysisList) {

        // 获取学生答题信息
        List<ResourceInteractionLogResultDTO> interactionList = new ArrayList<>();
        List<ResourceAnswerDTO> answerList = new ArrayList<>();

        // 判断是资料还是互动视频 获取答题数据
        if (Objects.equals(CourseContentTypeEnum.DATA.getCode(), part.getItemType())) {
            interactionList = this.getDataAnswer(part, answerList);
        } else {
            interactionList = this.getVideoAnswer(part, answerList);
        }
        Integer answerCount = interactionList.size();

        // 校验答题数据
        this.initPartAnswer(part, analysisList, answerCount, answerList, interactionList);

    }

    /**
     * 获取资料答题数据
     * @author dzy
     */
    private List<ResourceInteractionLogResultDTO> getDataAnswer(CourseResourcePartEntity part, List<ResourceAnswerDTO> answerList) {
        List<ResourceInteractionLogResultDTO> interactionList = resourceInteractionLogManage.findList(part.getContentId(), part.getResourceId());
        interactionList.forEach(item -> {
            item.getAnswer().forEach(answer -> {
                answer.setStudentId(item.getStudentId());
                answerList.add(answer);
            });
        });
        return interactionList;
    }

    /**
     * 获取互动试题答题数据
     * @author dzy
     */
    private List<ResourceInteractionLogResultDTO> getVideoAnswer(CourseResourcePartEntity part, List<ResourceAnswerDTO> answerList) {
        List<ResourceInteractionLogResultDTO> interactionList = resourceInteractionLogManage.findList(part.getContentId(), part.getId());
        interactionList.forEach(item -> {
            item.getAnswer().forEach(answer -> {
                answer.setStudentId(item.getStudentId());
                answerList.add(answer);
            });
        });
        // 获取旧库答题记录
        InteractionSubmitQueryDTO query = new InteractionSubmitQueryDTO();
        query.setContentId(part.getContentId());
        query.setResourcePartId(part.getId());
        List<CourseInteractionSubmitResult> answerOldList = courseInteractionSubmitManager.studentAnswerList(query);
        if (CollectionUtils.isNotEmpty(answerOldList)) {
            // 赋值用户答题记录
            if (CollectionUtils.isEmpty(interactionList)) {
                interactionList = new ArrayList<>();
            }
            List<ResourceInteractionLogResultDTO> oldInteractionList = resourceInteractionLogConvert.convertSubmitResult(answerOldList);
            interactionList.addAll(oldInteractionList);
            // 去重复 根据 studentId
            if (CollectionUtils.isNotEmpty(interactionList)) {
                interactionList = interactionList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
                    Comparator.comparing(ResourceInteractionLogResultDTO::getStudentId))), ArrayList::new));
            }

            // 赋值答题数据
            answerList.addAll(courseResourceAnswerConvert.convertSubmitResult(answerOldList));
        }
        return interactionList;
    }

    /**
     * 校验答题数据
     * @author dzy
     */
    private void initPartAnswer(CourseResourcePartEntity part, List<QuestionAnalysisResultDTO> analysisList
        , Integer answerCount, List<ResourceAnswerDTO> answerList, List<ResourceInteractionLogResultDTO> interactionList) {
        for (QuestionAnalysisResultDTO analysis : analysisList) {
            analysis.setContentId(part.getContentId());
            analysis.setPartId(part.getId());
            // 赋值参与答题总人数
            analysis.setAllNumber(answerCount);
            List<ResourceAnswerDTO> questionAnswerList = new ArrayList<>();
            answerList.forEach(item -> {
                if (Objects.equals(analysis.getId(), item.getQuestionId())) {
                    questionAnswerList.add(item);
                }
            });
            // 计算得分率
            this.answerRightRate(analysis, questionAnswerList, answerCount);
            // 计算选项分布率
            this.optionRate(analysis, questionAnswerList,  answerCount, interactionList);
        }
    }

    /**
     * 获取试题得分率
     * @author dzy
     */
    private void answerRightRate(QuestionAnalysisResultDTO question, List<ResourceAnswerDTO> answerList, Integer count) {
        BigDecimal scoreRate = new BigDecimal(0);
        List<ResourceAnswerDTO> rightAnswerList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(answerList) && count > 0) {
            rightAnswerList = answerList.stream().filter(v -> v.getIsRight()).collect(Collectors.toList());
            scoreRate = new BigDecimal(rightAnswerList.size()).divide(new BigDecimal(count), 2, BigDecimal.ROUND_HALF_UP);
        }
        question.setRightNumber(rightAnswerList.size());
        question.setScoreRate(MathUtils.stripTrailingZeros(scoreRate, 2));
    }

    /**
     * 获取选项答题人数
     * @author dzy
     */
    private void optionRate(QuestionAnalysisResultDTO question, List<ResourceAnswerDTO> answerList, Integer count, List<ResourceInteractionLogResultDTO> interactionList) {
        if (Objects.nonNull(question)) {
            question.getOptionList().forEach(option -> {
                if (CollectionUtils.isNotEmpty(answerList)) {
                    List<ResourceAnswerDTO> selList = answerList.stream().filter(v -> v.getStudentAnswer().contains(option.getId())).collect(Collectors.toList());
                    List<Long> studentIds = selList.stream().map(ResourceAnswerDTO::getStudentId).collect(Collectors.toList());
                    List<ResourceInteractionLogResultDTO> answerUsers = interactionList.stream().filter(v -> studentIds.contains(v.getStudentId())).collect(Collectors.toList());
                    option.setStudentNum(selList.size());
                    option.setStudentList(courseResourceAnswerConvert.convert(answerUsers));
                    if (count == 0) {
                        option.setSelectRate(new BigDecimal(0));
                    } else {
                        BigDecimal optionRate = new BigDecimal(selList.size()).divide(new BigDecimal(count), 2, BigDecimal.ROUND_HALF_UP);
                        option.setSelectRate(MathUtils.stripTrailingZeros(optionRate, 1));
                    }
                } else {
                    option.setStudentNum(0);
                    option.setStudentList(new ArrayList<>());
                    option.setSelectRate(new BigDecimal(0));
                }
            });
        } else {
            question.getOptionList().forEach(option -> {
                option.setStudentNum(0);
                option.setStudentList(new ArrayList<>());
                option.setSelectRate(new BigDecimal(0));
            });
        }
    }

    /**
     * 获取 答题答对 答错 学生列表
     * @author dzy
     */
    @Override
    public List<ResourceStudentLogUserResultDTO> answerDetails(ResourceQuestionAnalysisQueryDTO query) {

        // 获取互动环节
        CourseResourcePartEntity part = getPartById(query.getPartId());
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(part), "未获取到互动环节");

        // 获取试题
        QuestionBaseDTO questionBase = part.getQuestions().stream().filter(v -> Objects.equals(query.getQuestionId(), v.getId()))
            .collect(Collectors.toList()).get(0);
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(questionBase), "未获取到试题");

        // 获取答题人员
        List<ResourceInteractionLogResultDTO> interactionList = new ArrayList<>();
        List<ResourceInteractionLogResultDTO> rightList = new ArrayList<>();
        if (Objects.equals(CourseContentTypeEnum.DATA.getCode(), part.getItemType())) {
            interactionList = resourceInteractionLogManage.findList(query.getContentId(), part.getResourceId());
            interactionList.forEach(item -> {
                item.getAnswer().forEach(answer -> {
                    // 获取答对人员集合
                    if (Objects.equals(query.getQuestionId(), answer.getQuestionId())) {
                        if (QuestionUtil.checkAnswer(questionBase, answer.getStudentAnswer())) {
                            rightList.add(item);
                        }
                    }
                });
            });
        } else {
            interactionList = resourceInteractionLogManage.findList(query.getContentId(), part.getId());
            interactionList.forEach(item -> {
                // 获取答对人员集合
                item.getAnswer().forEach(answer -> {
                    if (Objects.equals(query.getQuestionId(), answer.getQuestionId())) {
                        // 获取答对人员集合
                        if (Objects.equals(query.getQuestionId(), answer.getQuestionId())) {
                            if (QuestionUtil.checkAnswer(questionBase, answer.getStudentAnswer())) {
                                rightList.add(item);
                            }
                        }
                    }
                });
            });
        }
        if (Objects.equals(YesNoNumberEnum.YES.getCode(), query.getStats())) {
            return resourceInteractionLogConvert.convert(rightList);
        } else {
            interactionList.removeAll(rightList);
            return resourceInteractionLogConvert.convert(interactionList);
        }
    }


}
